package com.cskaoyan.day03.stack;

/**
 * @author stone
 * @date 2022/01/29 15:44
 */
public class ArrayStack<T> {
    Object[] elements;//数组用来存放数据
    private int size;
    private static final int INIT_CAPACITY = 10;
    private static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;

    //给到数组一个默认的容量
    public ArrayStack() {
        elements = new Object[INIT_CAPACITY];
    }

    //也可以提供一个包含容量参数的构造方法
    public ArrayStack(int capacity) {
        if (capacity < 1 || capacity > MAX_CAPACITY) {
            throw new RuntimeException("容量不合法");
        }
        elements = new Object[capacity];
    }



    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    //push是向数组里放入数据 → 有可能要扩容
    public boolean push(T value) {
        //如何判断数组满了
        if (elements.length == size) {
            //满了就要扩容
            int newLength = getLength();
            grow(newLength);
        }

        elements[size] = value;
        size++;
        return true;
    }

    //扩容  → 新增新数组 、旧数组数据迁移 、 elements指向新数组
    private void grow(int newLength) {
        Object[] newElements = new Object[newLength];
        //旧数组数据迁移
        for (int i = 0; i < elements.length; i++) {
            newElements[i] = elements[i];
        }
        //elements指向新数组
        elements = newElements;
    }

    //计算新数组的长度
    private int getLength() {
        //根据当前数组的长度来计算新数组长度
        int oldLength = elements.length; //size也可以
        //int newLength = oldLength + oldLength >> 1;//1.5倍
        int newLength = oldLength << 1;
        //如果变为负数或已经超过最大容量
        if (newLength < 0 || newLength > MAX_CAPACITY) {
            newLength = MAX_CAPACITY;
        }
        if (oldLength == newLength) {//已经是最大容量
            throw new RuntimeException("已经是最大容量了");
        }

        return newLength;
    }

    public T pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空");
        }
        T value = (T) elements[size - 1];
        size--;

        return value;
    }

    public T peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空");
        }
        T value = (T) elements[size - 1];

        return value;
    }
}
